#include "../include/socket.hpp"
#include <string.h>

//default ctor
Socket::Socket() : addressFamily_( AF_INET ), protocol_( 0 ) {
	WSAStart();
}

//copy ctor
Socket::Socket( const Socket& socket ) : service_( socket.service_ ), hSocket_( socket.hSocket_ ), addressFamily_( socket.addressFamily_ ), protocol_( socket.protocol_ ) { 
	WSAStart();
}

//ctor
Socket::Socket( ADDRESS_FAMILY addressFamily, USHORT protocol ) : addressFamily_( addressFamily ), protocol_( protocol ) {
	WSAStart();
}

void Socket::WSAStart() {
	//automatic wsa startup
	WSADATA	wsaData;
	int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
	if( iResult != NO_ERROR ) {
		//std::cerr << "WSAStartup failed" << std::endl;
		//return EXIT_FAILURE;
	}

	hSocket_ = socket( addressFamily_, SOCK_STREAM, protocol_ );
	if( hSocket_ == INVALID_SOCKET ) {
		std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl;
		//exitCode = EXIT_FAILURE;
		//goto cleanup;
	}
}

bool Socket::Accept( Socket &clientSocket ) {
	clientSocket.hSocket_ = accept( hSocket_, NULL, NULL );
	return clientSocket.hSocket_ != SOCKET_ERROR;
}

bool Socket::Bind( std::string address, int port ) {
	service_.sin_family = addressFamily_;
	service_.sin_addr.s_addr = inet_addr( address.c_str() );
	service_.sin_port = htons( port );

	return bind( hSocket_, (SOCKADDR*) &service_, sizeof(service_) ) != SOCKET_ERROR;
}

bool Socket::Connect( std::string address, int port ) {
	service_.sin_family = addressFamily_;
	service_.sin_addr.s_addr = inet_addr( address.c_str() );
	service_.sin_port = htons( port );

	return connect( hSocket_, (SOCKADDR*) &service_, sizeof(service_) ) != SOCKET_ERROR;
}

bool Socket::Listen() {
	return listen( hSocket_, 1 ) != SOCKET_ERROR;
}

int Socket::Receive( char* recvbuf, int len ) {
	return recv( hSocket_, recvbuf, len + 1, 0 ) != SOCKET_ERROR;
}


int Socket::Send( const char* sendbuf ) {
	return send( hSocket_, sendbuf, strlen( sendbuf ) + 1, 0 );
}

void Socket::Close() {
	//automatic wsa cleanup
	closesocket( hSocket_ );
	WSACleanup();
}


Socket::~Socket() {
	Close();
}